import tkinter as tk
from tkinter import messagebox

class GoGame:
    def __init__(self, master):
        self.master = master
        self.master.title('围棋')
        self.board_size = 19  # 19路棋盘
        self.cell_size = 30   # 每个格子的大小
        self.margin = 20      # 边距
        
        # 棋盘状态：0表示空，1表示黑棋，2表示白棋
        self.board = [[0 for _ in range(self.board_size)] for _ in range(self.board_size)]
        self.current_player = 1  # 1是黑棋，2是白棋
        self.last_board = None   # 记录上一步棋盘状态，用于打劫判断
        self.ko_point = None     # 打劫点
        self.game_over = False
        self.passes = 0          # 连续过的次数
        
        self.setup_ui()
        
    def setup_ui(self):
        # 创建画布
        canvas_size = self.board_size * self.cell_size + 2 * self.margin
        self.canvas = tk.Canvas(self.master, width=canvas_size, height=canvas_size, bg='#DEB887')
        self.canvas.pack(side=tk.LEFT)
        
        # 创建控制面板
        control_panel = tk.Frame(self.master)
        control_panel.pack(side=tk.RIGHT, padx=20)
        
        tk.Button(control_panel, text='过子', command=self.pass_move).pack(pady=5)
        tk.Button(control_panel, text='认输', command=self.resign).pack(pady=5)
        tk.Button(control_panel, text='计算胜负', command=self.calculate_score).pack(pady=5)
        
        # 绘制棋盘
        self.draw_board()
        
        # 绑定鼠标点击事件
        self.canvas.bind('<Button-1>', self.handle_click)
        
    def draw_board(self):
        # 清空画布
        self.canvas.delete('all')
        
        # 画棋盘线
        for i in range(self.board_size):
            # 横线
            self.canvas.create_line(
                self.margin, self.margin + i * self.cell_size,
                self.margin + (self.board_size-1) * self.cell_size,
                self.margin + i * self.cell_size
            )
            # 竖线
            self.canvas.create_line(
                self.margin + i * self.cell_size, self.margin,
                self.margin + i * self.cell_size,
                self.margin + (self.board_size-1) * self.cell_size
            )
        
        # 画天元和星位
        star_points = [3, 9, 15] if self.board_size == 19 else [2, 6] if self.board_size == 9 else []
        for i in star_points:
            for j in star_points:
                x = self.margin + i * self.cell_size
                y = self.margin + j * self.cell_size
                self.canvas.create_oval(x-3, y-3, x+3, y+3, fill='black')
        
        # 画棋子
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.board[i][j] != 0:
                    self.draw_stone(i, j)
                    
    def draw_stone(self, row, col):
        x = self.margin + col * self.cell_size
        y = self.margin + row * self.cell_size
        color = 'black' if self.board[row][col] == 1 else 'white'
        self.canvas.create_oval(
            x - self.cell_size//2 + 2,
            y - self.cell_size//2 + 2,
            x + self.cell_size//2 - 2,
            y + self.cell_size//2 - 2,
            fill=color,
            outline='black'
        )
        
    def handle_click(self, event):
        if self.game_over:
            return
            
        # 将点击位置转换为棋盘坐标
        col = round((event.x - self.margin) / self.cell_size)
        row = round((event.y - self.margin) / self.cell_size)
        
        if 0 <= row < self.board_size and 0 <= col < self.board_size:
            self.make_move(row, col)
            
    def make_move(self, row, col):
        if self.board[row][col] != 0:
            return
            
        # 保存当前棋盘状态用于打劫判断
        self.last_board = [row[:] for row in self.board]
        
        # 放置棋子
        self.board[row][col] = self.current_player
        
        # 检查是否有提子
        captured = self.check_captures(row, col)
        
        # 检查打劫
        if self.ko_point == (row, col):
            self.board = [row[:] for row in self.last_board]
            messagebox.showinfo("提示", "打劫了，这一手不能下！")
            return
            
        # 检查自杀手
        if not captured and not self.has_liberty(row, col):
            self.board = [row[:] for row in self.last_board]
            messagebox.showinfo("提示", "自杀手，这一手不能下！")
            return
            
        # 更新打劫点
        self.ko_point = None
        if len(captured) == 1:
            self.ko_point = captured[0]
            
        # 重置连续过子计数
        self.passes = 0
        
        # 切换玩家
        self.current_player = 3 - self.current_player
        
        # 重绘棋盘
        self.draw_board()
        
    def check_captures(self, row, col):
        captured = []
        for dr, dc in [(-1,0), (1,0), (0,-1), (0,1)]:
            r, c = row + dr, col + dc
            if 0 <= r < self.board_size and 0 <= c < self.board_size:
                if self.board[r][c] == 3 - self.current_player:  # 对手的棋子
                    if not self.has_liberty(r, c):
                        group = self.get_group(r, c)
                        for stone_r, stone_c in group:
                            self.board[stone_r][stone_c] = 0
                            captured.append((stone_r, stone_c))
        return captured
        
    def has_liberty(self, row, col):
        color = self.board[row][col]
        checked = set()
        
        def check_liberty(r, c):
            if (r, c) in checked:
                return False
            checked.add((r, c))
            
            # 找到空点就有气
            if self.board[r][c] == 0:
                return True
                
            # 不是同色棋子
            if self.board[r][c] != color:
                return False
                
            # 检查相邻点
            for dr, dc in [(-1,0), (1,0), (0,-1), (0,1)]:
                next_r, next_c = r + dr, c + dc
                if 0 <= next_r < self.board_size and 0 <= next_c < self.board_size:
                    if check_liberty(next_r, next_c):
                        return True
            return False
            
        return check_liberty(row, col)
        
    def get_group(self, row, col):
        color = self.board[row][col]
        group = set()
        
        def add_to_group(r, c):
            if (r, c) in group or self.board[r][c] != color:
                return
            group.add((r, c))
            for dr, dc in [(-1,0), (1,0), (0,-1), (0,1)]:
                next_r, next_c = r + dr, c + dc
                if 0 <= next_r < self.board_size and 0 <= next_c < self.board_size:
                    add_to_group(next_r, next_c)
                    
        add_to_group(row, col)
        return group
        
    def pass_move(self):
        self.passes += 1
        self.current_player = 3 - self.current_player
        if self.passes >= 2:
            self.game_over = True
            self.calculate_score()
            
    def resign(self):
        self.game_over = True
        winner = "白棋" if self.current_player == 1 else "黑棋"
        messagebox.showinfo("游戏结束", f"{winner}胜！")
        
    def calculate_score(self):
        # 简单的数子法计算胜负
        black_count = sum(row.count(1) for row in self.board)
        white_count = sum(row.count(2) for row in self.board)
        
        # 白棋贴目3.75
        komi = 3.75
        white_count += komi
        
        if black_count > white_count:
            messagebox.showinfo("计分", f"黑棋胜 {black_count - white_count} 目")
        else:
            messagebox.showinfo("计分", f"白棋胜 {white_count - black_count} 目")

def main():
    root = tk.Tk()
    game = GoGame(root)
    root.mainloop()

if __name__ == "__main__":
    main() 